package com.xuecheng.content.service.impl;

import com.alibaba.fastjson.JSON;
import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.content.config.MultipartSupportConfig;
import com.xuecheng.content.feignclient.MediaServiceClient;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.mapper.CourseMarketMapper;
import com.xuecheng.content.mapper.CoursePublishMapper;
import com.xuecheng.content.mapper.CoursePublishPreMapper;
import com.xuecheng.content.model.dto.CourseBaseInfoDto;
import com.xuecheng.content.model.dto.CoursePreviewDto;
import com.xuecheng.content.model.dto.TeachplanDto;
import com.xuecheng.content.model.po.CourseBase;
import com.xuecheng.content.model.po.CourseMarket;
import com.xuecheng.content.model.po.CoursePublish;
import com.xuecheng.content.model.po.CoursePublishPre;
import com.xuecheng.content.service.CourseBaseInfoService;
import com.xuecheng.content.service.CoursePublishService;
import com.xuecheng.content.service.TeachpanService;
import com.xuecheng.messagesdk.service.MqMessageService;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.core.util.JsonUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class CoursePublishServiceImpl implements CoursePublishService {

    @Autowired
    CourseBaseInfoService courseBaseInfoService;

    @Autowired
    TeachpanService teachpanService;

    @Autowired
    CourseBaseMapper courseBaseMapper;

    @Autowired
    CoursePublishMapper coursePublishMapper;

    @Autowired
    CourseMarketMapper courseMarketMapper;

    @Autowired
    CoursePublishPreMapper coursePublishPreMapper;

    @Autowired
    MqMessageService mqMessageService;

    @Autowired
    MediaServiceClient mediaServiceClient;


    @Override
    public CoursePreviewDto getCoursePreviewInfo(Long courseId) {
        CoursePreviewDto coursePreviewInfo = new CoursePreviewDto();
        //课程基本信息，营销信息
        CourseBaseInfoDto courseBaseInfo = courseBaseInfoService.getCourseBaseInfo(courseId);
        coursePreviewInfo.setCourseBase(courseBaseInfo);

        //课程计划信息
        List<TeachplanDto> teachplanTree = teachpanService.findTeachplanTree(courseId);
        coursePreviewInfo.setTeachplans(teachplanTree);
        return coursePreviewInfo;
    }


    @Override
    @Transactional
    public void commitAudit(Long companyId, Long courseId) {

        CourseBaseInfoDto courseBaseInfo = courseBaseInfoService.getCourseBaseInfo(courseId);
        if (courseBaseInfo == null) {
            XueChengPlusException.cast("课程找不到");
        }

        //审核状态
        String auditStatus = courseBaseInfo.getAuditStatus();

        //如果课程审核状态为已提交，则不允许再次提交
        if ("202003".equals(auditStatus)) {
            XueChengPlusException.cast("课程已提交审核，请等待结果");
        }

        //课程的图片，计划，课程计没有的话也不允许提交
        String pic = courseBaseInfo.getPic();
        if (StringUtils.isEmpty(pic)) {
            XueChengPlusException.cast("提交课程审核前，必须上传课程图片");
        }
        //本机构的课程，只允许提交本机构的课程
        if (!companyId.equals(courseBaseInfo.getCompanyId())) {
            XueChengPlusException.cast("本机构只能提交本机构的课程");
        }
        //查询课程计划
        List<TeachplanDto> teachplanTree = teachpanService.findTeachplanTree(courseId);
        if (teachplanTree == null || teachplanTree.size() <= 0) {
            XueChengPlusException.cast("提交课程审核前，必须添加课程计划");
        }

        //查询课程基本信息，营销信息，计划等信息，插入到课程预发布表
        CoursePublishPre coursePublishPre = new CoursePublishPre();
        BeanUtils.copyProperties(courseBaseInfo, coursePublishPre);
        //机构id
        coursePublishPre.setCompanyId(companyId);
        //营销信息
        CourseMarket courseMarket = courseMarketMapper.selectById(courseId);
        //转成json
        String courseMarketJson = JSON.toJSONString(courseMarket);
        coursePublishPre.setMarket(courseMarketJson);

        //计划信息
        //转成json
        String teachplanTreeJson = JSON.toJSONString(teachplanTree);
        coursePublishPre.setTeachplan(teachplanTreeJson);

        //状态wei 已提交
        coursePublishPre.setStatus("202003");

        //提交时间
        coursePublishPre.setCreateDate(LocalDateTime.now());

        //查询预发布表，如果存在则更新，不存在则添加
        CoursePublishPre coursePublishPreOld = coursePublishPreMapper.selectById(courseId);
        if (coursePublishPreOld == null) {
            //添加
            coursePublishPreMapper.insert(coursePublishPre);
        } else {
            //更新
            coursePublishPreMapper.updateById(coursePublishPre);
        }

        //更新课程基本信息表的审核状态为已提交
        CourseBase courseBase = courseBaseMapper.selectById(courseId);
        courseBase.setAuditStatus("202003");//审核状态为已提交
        courseBaseMapper.updateById(courseBase);

    }

    @Override
    public void publish(Long companyId, Long courseId) {

        //查询预发布表
        CoursePublishPre coursePublishPre = coursePublishPreMapper.selectById(courseId);
        if (coursePublishPre == null) {
            XueChengPlusException.cast("课程没有审核");
        }
        //状态
        String status = coursePublishPre.getStatus();
        if (!"202004".equals(status)) {
            XueChengPlusException.cast("课程没有审核通过，不能发布");
        }
        //向课程发布表写入数据
        CoursePublish coursePublish = new CoursePublish();
        BeanUtils.copyProperties(coursePublishPre, coursePublish);
        CoursePublish coursePublishObj = coursePublishMapper.selectById(courseId);
        if (coursePublishObj == null) {
            coursePublishMapper.insert(coursePublish);
        } else {
            coursePublishMapper.updateById(coursePublish);
        }

        //向消息表写入数据
        mqMessageService.addMessage("course_publish", String.valueOf(courseId), null, null);

        //将预发布表数据删除
        coursePublishPreMapper.deleteById(courseId);

    }

    /**
     * 生成课程静态化页面
     *
     * @param courseId 课程id
     * @return
     */
    @Override
    public File generateCourseHtml(Long courseId) {
        Configuration configuration = new Configuration(Configuration.getVersion());

        //最终的静态文件
        File htmlFile = null;

        try {
            //使用ClassPathResource来获取模板路径，避免在测试环境中路径问题
            //设置模版路径 - 使用ClassLoader来获取资源
            configuration.setClassForTemplateLoading(this.getClass(), "/templates/");
            //设置字符集
            configuration.setDefaultEncoding("utf-8");
            //得到模版
            Template template = configuration.getTemplate("course_template.ftl");


            //获取数据
            CoursePreviewDto coursePreviewInfo = this.getCoursePreviewInfo(courseId);

            Map<String, Object> map = new HashMap<>();
            map.put("model", coursePreviewInfo);


            //模版，数据

            String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);

            System.out.println(html);


            //输入流
            InputStream inputStream = IOUtils.toInputStream(html, "utf-8");
            //临时文件
            htmlFile = File.createTempFile("coursepublish", ".html");
            //输出文件
            FileOutputStream outputStream = new FileOutputStream(htmlFile);

            //使用流将HTML写入文件
            IOUtils.copy(inputStream, outputStream);
        } catch (Exception e) {
            log.error("页面静态化异常，课程id：{}", courseId, e);
            e.printStackTrace();


        }

        return htmlFile;
    }

    /**
     * 上传课程静态化页面dao minio
     * @param courseId
     * @param file  静态化文件
     */
    @Override
    public void uploadCourseHtml(Long courseId, File file) {

        try {
            //将File转换成MultipartFile
            MultipartFile multipartFile = MultipartSupportConfig.getMultipartFile(file);

            String upload = mediaServiceClient.uploadFile(multipartFile, "course/" + courseId + ".html");

            if (upload == null) {
                log.error("上传静态化页面异常,课程ID：{}", courseId);
                XueChengPlusException.cast("上传静态化页面异常");
            }

        } catch (Exception e) {
            e.printStackTrace();
            XueChengPlusException.cast("上传静态化页面异常");
        }


    }


}
